<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>第九章：实际应用案例 - 9.4 开发一个简单的聊天机器人</title>
    <link rel="stylesheet" href="../shared_styles.css">
</head>
<body>
    <div class="container">
        <h1> 第九章：实际应用案例</h1>
        <section id="s9-4">
            <h2>9.4 开发一个简单的聊天机器人</h2>
            <p>聊天机器人是LLM最常见的应用之一。在本节中，我们将构建一个简单的聊天机器人，它能回答单轮问题，但不具备理解对话上下文的能力。</p>
            <p>主要步骤包括：</p>
            <ol>
                <li>初始化Qwen聊天模型。</li>
                <li>设计一个包含系统消息（定义机器人角色）和用户输入占位符的聊天提示模板。</li>
                <li>使用LCEL将模型和提示模板组合起来，构建一个简单的Runnable。</li>
                <li>进行多轮对话测试，观察其单轮问答能力。</li>
            </ol>

            <h3>准备工作：初始化和导入</h3>
            <pre><code class="language-python">
from langchain_openai import ChatOpenAI # Qwen兼容
from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate
from langchain_core.runnables import Runnable
from dotenv import load_dotenv
import os

# 加载环境变量
load_dotenv()
api_key = os.environ.get("DASHSCOPE_API_KEY")
if not api_key:
    raise ValueError("DASHSCOPE_API_KEY not found. Please set it in your .env file.")

# 初始化Qwen聊天模型
qwen_llm = ChatOpenAI(
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key=api_key,
    model="qwen-plus",
    temperature=0.7, # 聊天机器人可以有适度的创造性
    streaming=False
)
print("Qwen LLM 初始化成功。")
            </code></pre>

            <h3>步骤1：定义聊天机器人的角色</h3>
            <p>我们将赋予机器人一个友好、乐于助人的角色。</p>
            <pre><code class="language-python">
# 定义系统消息，赋予机器人角色
system_message_content = (
    "你是一个名为“灵犀”的AI助手，你的目标是友好且耐心地帮助用户解决问题。"
    "你只能回答当前用户提出的问题，不具备记忆之前对话内容的能力。"
)

print("聊天机器人角色定义完毕。")
            </code></pre>
            <p>这个机器人不具备记忆能力，每次交互都是独立的。</p>

            <h3>步骤2：创建聊天提示模板</h3>
            <p>提示模板只需要包含系统消息和当前用户输入的占位符。</p>
            <pre><code class="language-python">
# 创建聊天提示模板
# SystemMessagePromptTemplate 用于系统消息
# HumanMessagePromptTemplate 用于当前用户输入
chat_prompt_template = ChatPromptTemplate.from_messages([
    SystemMessagePromptTemplate.from_template(system_message_content),
    HumanMessagePromptTemplate.from_template("{input}") # 用户当前的输入
])
print("聊天提示模板创建完毕。")
            </code></pre>

            <h3>步骤3：构建简单的Runnable (使用LCEL)</h3>
            <p>我们使用LCEL构建一个简单的Runnable，将提示模板和模型连接起来。</p>
            <pre><code class="language-python">
# 构建简单的LCEL Runnable
# 这个Runnable接收一个字典作为输入，其中包含 'input'
chatbot_runnable = chat_prompt_template | qwen_llm

print("简单的Runnable 构建成功！")
            </code></pre>
            <p>这个Runnable不包含任何记忆逻辑，每次调用都是独立的。</p>

            <h3>步骤4：进行多轮对话测试</h3>
            <p>现在我们可以和聊天机器人进行多轮对话，观察它是否能回答单轮问题。</p>
            <pre><code class="language-python">
# 定义一个函数来处理用户输入并与机器人交互
def chat_with_bot(user_input):
    print(f"用户: {user_input}")
    try:
        # 调用 invoke 方法，传入用户输入
        response = chatbot_runnable.invoke({"input": user_input})
        # invoke 返回的是 LLM 的输出消息对象
        ai_response = response.content
        print(f"灵犀: {ai_response}")
        return ai_response
    except Exception as e:
        print(f"与机器人对话时出错: {e}")
        return None

print(f"\n--- 开始与“灵犀”聊天 (输入 '退出' 来结束) ---")

# 第一轮对话
chat_with_bot("你好，灵犀！你今天感觉怎么样？")

# 第二轮对话
chat_with_bot("我最近在学习Langchain框架，你对它有什么了解吗？")

# 第三轮对话 - 观察是否能记住上一轮内容 (预期不能)
chat_with_bot("它有哪些核心组件呢？")

# 第四轮对话
chat_with_bot("我叫小明，你能记住我的名字吗？")

# 第五轮对话 - 观察是否能记住之前的名字 (预期不能)
chat_with_bot("你还记得我叫什么名字吗？")

print("\n--- 聊天结束 ---")
            </code></pre>
            <p>在运行这段代码时，请注意观察：</p>
            <ul>
                <li>机器人“灵犀”能否回答每个独立的单轮问题。</li>
                <li>在第三轮和第五轮对话中，机器人将无法记住之前对话的内容，因为我们已经移除了记忆功能。</li>
            </ul>
            <p>通过设置适当的日志级别，你将能看到每次发送给Qwen模型的完整提示，它只包含系统消息和当前用户输入。</p>

            <h3>总结</h3>
            <p>通过结合Langchain的提示模板和强大的LLM（如Qwen），我们可以构建出简单的单轮问答聊天机器人。如果需要具备上下文理解能力，则需要引入Memory模块和相应的Runnable（如<code>RunnableWithMessageHistory</code>）。</p>
            <p>对于更复杂的应用场景，你可能需要：</p>
            <ul>
                <li>引入Memory模块，使其具备上下文理解能力（参考本节之前的版本或相关章节）。</li>
                <li>将RAG（检索增强生成）与聊天机器人结合，使其能查询外部知识库来回答问题（参考9.1节）。</li>
                <li>为机器人集成工具（Tool），使其能执行查询天气、计算等操作（参考第五章Agents模块）。</li>
            </ul>
        </section>

        <div class="navigation">
            <a href="../langchain_tutorial_outline.html">返回教程目录</a>
            <a href="../chapter9/chapter9_application_extraction.html">上一节：9.3 从文本中提取结构化信息</a>
            <!-- <a href="../chapter9/chapter9_application_custom_agent.html">下一节：9.5 如何利用Langchain和提示词构建具有特定角色的AI应用</a> -->
        </div>
    </div>
</body>
</html>
